import java.lang.reflect.*;
import java.util.Arrays;

public class JShellParserTest {

	public JShellParserTest() {
	}

	public String[] publicParser(String input) {
		JShell shell = new JShell();
		try {
			Class<?>[] arguments = { String.class };
			Method privateParser = JShell.class.getDeclaredMethod("parseInput",
					arguments);
			privateParser.setAccessible(true);
			return (String[]) privateParser.invoke(shell, input);
		} catch (Exception e) {
			System.err.println(e);
			return null;
		}
	}

	// Return string representation of a string-array.
	// Only used when a test fails, to help diagnose
	// the problem.
	public String arrayToString(String[] inputarray) {
		String output = "[ ";
		for (String x : inputarray) {
			output += "'" + x + "' ";
		}
		output += "]";
		return output;
	}

	public void testParseOutput(String input, String[] correctOutput) {
		String[] output = publicParser(input);
		assert (Arrays.equals(output, correctOutput));
	}

	public static void main(String[] args) {
		JShellParserTest test = new JShellParserTest();
		String input;

		// *** Test *** Empty Cases:
		// ************
		
		// Empty string
		input = "";
		String[] correctOutput = {};
		test.testParseOutput("", correctOutput);

		// Single tab
		input = "\t";
		String[] correctOutput1 = {};
		test.testParseOutput(input, correctOutput1);

		// Mix of tabs and spaces
		input = " \t";
		String[] correctOutput2 = {};
		test.testParseOutput(input, correctOutput2);
		
		input = " \t ";
		String[] correctOutput3 = {};
		test.testParseOutput(input, correctOutput3);
		
		input = "\t \t";
		String[] correctOutput4 = {};
		test.testParseOutput(input, correctOutput4);
		
		// *** Test *** 1-word arrays:
		// ************

		input = "oneword";
		String[] correctOutput5 = {"oneword"};
		test.testParseOutput(input, correctOutput5);
		
		// one word with trailing space
		input = "oneword ";
		String[] correctOutput6 = {"oneword"};
		test.testParseOutput(input, correctOutput6);
		
		// one word with leading space
		input = " oneword";
		String[] correctOutput7 = {"oneword"};
		test.testParseOutput(input, correctOutput7);
		
		// one word with trailing tabs
		input = "oneword\t";
		String[] correctOutput8 = {"oneword"};
		test.testParseOutput(input, correctOutput8);
		
		// one word with leading tabs
		input = "\toneword";
		String[] correctOutput9 = {"oneword"};
		test.testParseOutput(input, correctOutput9);
		
		// *** Test *** Quotes:
		// ************

		// one word in quotes
		input = "\"oneword\"";
		String[] correctOutput10 = {"oneword"};
		test.testParseOutput(input, correctOutput10);
		
		// two words in quotes
		input = "\"two word\"";
		String[] correctOutput11 = {"two word"};
		test.testParseOutput(input, correctOutput11);
		
		// multiple whitespace in quotes
		input = "\"one  word\"";
		String[] correctOutput12 = {"one  word"};
		test.testParseOutput(input, correctOutput12);
		
		input = "\"  one  word  \"";
		String[] correctOutput13 = {"  one  word  "};
		test.testParseOutput(input, correctOutput13);
		
		// *** Test *** Whitespace outside of quotes:
		// ************

		// empty case
		input = "\\ ";
		String[] correctOutput14 = {};
		test.testParseOutput(input, correctOutput14);

		// multiple spaces
		input = "\\ \\ ";
		String[] correctOutput15 = {" "};
		test.testParseOutput(input, correctOutput15);
		
		// multiple spaces
		input = "\\ \\ h";
		String[] correctOutput16 = {"  h"};
		test.testParseOutput(input, correctOutput16);
		
		// legal whitespace in quotes
		input = "\" this is a quote \\ with \\ spaces like that\"";
		String[] correctOutput17 = {" this is a quote \\ with \\ spaces like that"};
		test.testParseOutput(input, correctOutput17);
		
		
		// *** Test *** Multi-element array:
		// ************

		// base case
		input = "two words";
		String[] correctOutput18 = {"two", "words"};
		test.testParseOutput(input, correctOutput18);
		
		// lots of erroneous whitespace & tabs
		input = "   \t\t  \t  two  \t  \t  words \t\t  \t";
		String[] correctOutput19 = {"two", "words"};
		test.testParseOutput(input, correctOutput19);
		
		// adding quotes
		input = "two words \"in quotes\"";
		String[] correctOutput20 = {"two", "words", "in quotes"};
		test.testParseOutput(input, correctOutput20);
		
		// quotes glued to non-quoted word 
		input = "two words\"in quotes\"";
		String[] correctOutput21 = {"two", "wordsin quotes"};
		test.testParseOutput(input, correctOutput21);
		
		// multi elements, with legal-whitespace 
		input = "\\   two words \\  \"in quotes\"";
		String[] correctOutput22 = {"two", "words","in quotes"};
		//System.out.println(test.arrayToString(test.publicParser(input)));
		test.testParseOutput(input, correctOutput22);

		// *** Test *** Command examples:
		// ************
		
		// command + regular path
		input = "cd /user/this";
		String[] correctOutput23 = {"cd", "/user/this"};
		test.testParseOutput(input, correctOutput23);
		
		// command + path with spaces
		input = "cd /user/this\\ is\\ a\\ file";
		String[] correctOutput24 = {"cd", "/user/this is a file"};
		test.testParseOutput(input, correctOutput24);
		
		System.out.println("All tests have passed.");
	}
}
